<?php

/**
 * 模板引擎类文件
 * 
 * Example: 模板语法 =>编译结果
 * {$var} => <?php echo $var;?>
 * {:$var} => $var
 * 
 * 常量：__STATIC__ => PHP常量STC_DIR目录的相对路径，方便外部CSS、JS等资源调用
 * 输出式函数调用：{F:strlen($a)} => <?php echo strlen($a);?>
 * 返回式函数调用：{:strlen($a)} => strlen($a)   Tip:方便代码嵌套运行
 * 
 * 展示原始内容：{literal} {$var} {/literal} => {$var}
 * 
 * 数组使用语法：
 * $array = array('one'=>'hello','two'=>'world');
 * {$array[0]} => <?php echo $array[0]?>
 * {$array['one']} => <?php echo $array['one']?>
 * 
 * 模板循环语法：
 *  {for($i=0;$i<10;$i++)}
 *  do something
 *  {/for}
 * 
 * {foreach($arr as $v)}
 *  value is {$v}
 * {/foreach}
 * 
 * {foreach($arr as $k=>$v)}
 *  key is {$k},value is {$v}
 * {/foreach}
 * 
 * 条件判断语法：
 *  {if($a<3)}
 *      do something
 *  {/if}
 * 
 * {if($a<3)}
 *      do something
 * {else}
 *      do else
 * {/if}
 * 
 * {if($a<3)}
 *      do something
 * {elseif($a<10)}
 *      do elseif
 * {else}
 *      do else
 * {/if}
 * 
 * {switch($a)}
 * {case 'one'}
 *      do something
 * {/case}
 * {case 'two'}
 *      do something
 * {/case}
 * {default}
 *      do something
 * {/switch}
 * 
 * 注释语法：
 * {# something note #}
 * 
 * @author 暮雨秋晨
 * @copyright 2014
 */
require_once 'V/TemplateCheck.php';
require_once 'V/TemplateCompile.php';
require_once 'V/TemplateException.php';

class Template
{
    private $TPL_VARIABLE = array(); //存储模板变量的数组
    private static $TPL_SUFFIX = 'html'; //模板后缀
    private static $LEFT_DELIMITER = '{'; //左边界符
    private static $RIGHT_DELIMITER = '}'; //右边界符
    private static $COMPILE = 'compile'; //编译文件
    private static $TEMPLATE = 'default'; //模板文件
    private static $COMPILE_DIR = '';
    private static $TEMPLATE_DIR = '';

    public static function setSuffix($suffix)
    {
        if (!empty($suffix)) {
            $suffix = trim($suffix, "\0\t\n\x0B\r ."); //删除左右两边指定字符
            self::$TPL_SUFFIX = $suffix;
            return true;
        }
    }

    public static function setDelimiter($left, $right)
    {
        $right = trim($right);
        $left = trim($left);
        if (!empty($left) && !empty($right)) {
            self::$LEFT_DELIMITER = $left;
            self::$RIGHT_DELIMITER = $right;
            return true;
        } else {
            throw new TemplateException('<b>Template::setDelimiter()</b> parameter error.',
                1);
            return false;
        }
    }

    public static function setCompileDir($dir)
    {
        $dir = trim($dir);
        if (!empty($dir)) {
            self::$COMPILE = $dir;
            return true;
        } else {
            throw new TemplateException('<b>Template::setCompileDir()</b> parameter error.',
                1);
            return false;
        }
    }

    public static function setTemplateDir($dir)
    {
        $dir = trim($dir);
        if (!empty($dir)) {
            self::$TEMPLATE = $dir;
            return true;
        } else {
            throw new TemplateException('<b>Template::setTemplateDir()</b> parameter error.',
                1);
            return false;
        }
    }

    public function __construct()
    {
        $templates_dir = TPL_DIR . self::$TEMPLATE . DS;
        if (!is_dir($templates_dir)) {
            throw new TemplateException('Template path does not exist.', 2);
            return false;
        }
        $complies_dir = RTM_DIR . self::$COMPILE . DS;
        if (!is_dir($complies_dir)) {
            throw new TemplateException('Compile path does not exist.', 2);
            return false;
        }
        self::$COMPILE_DIR = $complies_dir;
        self::$TEMPLATE_DIR = $templates_dir;
        return true;
    }

    /**
     * 分配模板变量
     */
    public function assign($key, $val)
    {
        $key = trim($key);
        if (!empty($key)) {
            $this->TPL_VARIABLE[$key] = $val;
            return true;
        } else {
            throw new TemplateException('Template variables failure distribution.', 0);
            return false;
        }
    }

    /**
     * 展示模板
     */
    public function display($tpl = '')
    {
        $tpl = trim($tpl);
        if (empty($tpl)) {
            $tpl = $_GET['c'] . '/' . $_GET['a'];
        }
        $tpl = str_replace('/', DS, $tpl) . '.' . self::$TPL_SUFFIX;
        $template_c = $tpl . '.php';
        $template_c = str_replace(DS, '_', $template_c);
        $template_c_path = self::$COMPILE_DIR . $template_c;

        if (!is_file($template_c_path) || (filemtime(self::$TEMPLATE_DIR . $tpl) >
            filemtime($template_c_path))) {
            $res = $this->loadTemplate($tpl);

            $tpl_syntax_debug = new TemplateCheck(self::$LEFT_DELIMITER, self::$RIGHT_DELIMITER,
                self::$TEMPLATE_DIR . $tpl);
            $tpl_syntax_debug->syntax_chk($res);

            $compile = new TemplateCompile(self::$LEFT_DELIMITER, self::$RIGHT_DELIMITER,
                self::$TEMPLATE_DIR, self::$TEMPLATE);
            $res = $compile->compile($res);

            file_put_contents($template_c_path, $res);

            extract($this->TPL_VARIABLE);

            include $template_c_path;
        } else {
            extract($this->TPL_VARIABLE);

            include $template_c_path;
        }
    }

    private function loadTemplate($tpl)
    {
        if (is_file($tpl_file = self::$TEMPLATE_DIR . $tpl)) {
            $res = file_get_contents($tpl_file);
            if (empty($res)) {
                return false;
            } else {
                return $res;
            }
        } else {
            throw new TemplateException('Template file [<b>' . $tpl .
                '</b>] does not exist.', 2);
        }
    }

}

?>